#pragma once

#include "Device.h"

#include <map>
#include <string>

namespace nexus {

class Network {
 public:
  Network(std::string name) : name_(name){};
  ~Network(){};

  Device&
  addDevice(std::string name) {
    nameToDevice_.emplace(
        std::piecewise_construct,
        std::forward_as_tuple(name),
        std::forward_as_tuple(name));
    nameToDevice_.at(name).network(this);
    return nameToDevice_.at(name);
  }

  void
  addLink(
      std::string dev1,
      std::string port1,
      std::string dev2,
      std::string port2) {
    if (nameToDevice_.find(dev1) == nameToDevice_.end()) {
      addDevice(dev1);
    }
    if (nameToDevice_.find(dev2) == nameToDevice_.end()) {
      addDevice(dev2);
    }

    Port& p1 = nameToDevice_.at(dev1).getOrCreatePort(port1);
    Port& p2 = nameToDevice_.at(dev2).getOrCreatePort(port2);
    p1.peer = &p2;
    p2.peer = &p1;
  }

  auto&
  nameToDevice() {
    return nameToDevice_;
  }

  auto&
  name() {
    return name_;
  }

  auto&
  token() {
    return token_;
  }

  void
  setToken(std::string token) {
    token_ = token;
  }

  auto& aps() { return aps_; }

 private:
  std::string name_;
  std::string token_;
  std::map<std::string, Device> nameToDevice_;
  std::set<HeaderSpace> aps_;
};

} // namespace nexus